Define a Repository interface per domain aggregate, implement with sql.DB, inject via constructor, and use sqlc for type-safe query generation. Tests use mock implementations or in-process SQLite.
sqlc generates type-safe Go functions from SQL queries — no reflection, full IDE support
One repository interface per aggregate (User, Order, Product) — not one god repository
Return domain errors (ErrNotFound) not database errors — decouple domain from persistence
Integration tests use testcontainers-go for a real Postgres — unit tests use mocks
Avoid leaking DB types (sql.NullString) into domain models — map at the repository layer